#include <windows.h>
#include <iostream>
#include <string>
#include <ctime>
#include <conio.h>
using namespace std;
bool snake[30][30];
int snake_length_max = 3;
int snake_length = 0;
int direction;//����
float howtime = 0;
bool kill = false;

struct coordinates//����
{
    int X;
    int Y;
};

struct snake_coordinates
{
    coordinates S_coordinates[900];
    int length;
};

snake_coordinates snake_c;

void gotoxy(int x, int y)  //����ƶ���(x,y)λ�ã��ƶ�����0,0��ʱ������������һ��һ���� 
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD pos;                                      
    pos.X = x;
    pos.Y = y;
    SetConsoleCursorPosition(handle, pos);
}                                //����

static void initialize_tu()//��ʼ����������
{
    for (int i = 0; i < 30; i++)
    {
        for (int s = 0; s < 30; s++)
        {
            snake[i][s] = false;
        }
    }
    snake[snake_c.S_coordinates[snake_length].X][snake_c.S_coordinates[snake_length].Y] = true;
}
static void draw(coordinates appear_coords)//���Ʊ���
{
    gotoxy(0, 0);
    cout << " = = = = = = = = = = = = = ̰ �� �� = = = = = = = = = = = = = =" << "    ����:" << snake_length_max - 3 << endl;
    for (int i = 0; i < 30; i++)
    {
        cout << "= ";
        for (int s = 0; s < 30; s++)
        {
            if (i == appear_coords.X && s == appear_coords.Y)
            {
                if (kill == true)
                {
                    cout << "X ";
                }
                else
                {
                    cout << "@ ";
                }
            }
            else {
                if (snake[i][s] == false)
                {
                    cout << "  ";
                }
                else {
                    cout << "O ";
                }
            }
            
        }cout << "=";
        if (i == 1)
        {
            cout << "    ʱ��:" << howtime;
        }if (i == 3)
        {
            cout << "    ʹ��W,A,S,D��";
        }if (i == 4)
        {
            cout << "    ���ƶ�,K����";
        }cout << endl;
    }
    cout << "= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =" << endl;
}
coordinates update_coordinates()//ˢ���������
{
    coordinates a;
    a.X = rand() % 30;
    a.Y = rand() % 30;
    return a;
}

int speed = 30;
int now = 0;//�ٶ�

static void snake_move()//���ƶ�
{
    if (now >= speed)
    {
        
        if (snake_length >= snake_length_max)
        {
            snake[snake_c.S_coordinates[0].X][snake_c.S_coordinates[0].Y] = false;
            for (int i = 0; i < snake_length; i++)
            {
                snake_c.S_coordinates[i].X = snake_c.S_coordinates[i + 1].X;
                snake_c.S_coordinates[i].Y = snake_c.S_coordinates[i + 1].Y;
            }
        }
        else
        {
            snake_c.S_coordinates[snake_length + 1].X = snake_c.S_coordinates[snake_length].X;// cout << snake_c.S_coordinates[snake_length + 1].X; system("pause");
            snake_c.S_coordinates[snake_length + 1].Y = snake_c.S_coordinates[snake_length].Y;
            snake_length++;
        }
        switch (direction)
        {
        case 0:snake[snake_c.S_coordinates[snake_length].X--][snake_c.S_coordinates[snake_length].Y] = true;//up
            break;
        case 1:snake[snake_c.S_coordinates[snake_length].X++][snake_c.S_coordinates[snake_length].Y] = true;//down
            break;
        case 2:snake[snake_c.S_coordinates[snake_length].X][snake_c.S_coordinates[snake_length].Y--] = true;//left
            break;
        case 3:snake[snake_c.S_coordinates[snake_length].X][snake_c.S_coordinates[snake_length].Y++] = true;//right
            break;
        }
        now = 0;
        
    }
    else {
        now++;
    }
    
}

static void game_over()
{
    system("cls");
    
    cout << "game over" << endl;
    system("pause");
    exit(0);
}

int main() 
{
    HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO CursorInfo;
    GetConsoleCursorInfo(handle, &CursorInfo);//��ȡ����̨�����Ϣ
    CursorInfo.bVisible = false; //���ؿ���̨���
    SetConsoleCursorInfo(handle, &CursorInfo);//���ÿ���̨���״̬

    srand(static_cast<unsigned int>(time(0)));//�Ե�ǰʱ��Ϊ�������������
    coordinates appear_coords;//������ֵ�����
    appear_coords = update_coordinates();
    direction = rand() % 4;


    snake_c.S_coordinates[snake_length].X = 14;//��ʼ����ͷ����X
    snake_c.S_coordinates[snake_length].Y = 14;//��ʼ����ͷ����Y
    

    initialize_tu();
  
    while (1)
    {
        howtime += 0.01;
        if (snake_c.S_coordinates[snake_length].X > 29 || snake_c.S_coordinates[snake_length].X < 0 || //�ж�X���Ƿ�����
            snake_c.S_coordinates[snake_length].Y > 29 || snake_c.S_coordinates[snake_length].Y < 0 || //�ж�Y���Ƿ�����
            (snake[snake_c.S_coordinates[snake_length].X][snake_c.S_coordinates[snake_length].Y] == true && snake_length > 4))//�ж��Ƿ�ײ���Լ�
        {
            if (snake_c.S_coordinates[snake_length].X > 29) { snake_c.S_coordinates[snake_length].X = 29; }
            if (snake_c.S_coordinates[snake_length].Y > 29) { snake_c.S_coordinates[snake_length].Y = 29; }
            if (snake_c.S_coordinates[snake_length].X < 0) { snake_c.S_coordinates[snake_length].X = 0; }
            if (snake_c.S_coordinates[snake_length].Y < 0) { snake_c.S_coordinates[snake_length].Y = 0; }
            appear_coords.X = snake_c.S_coordinates[snake_length].X; appear_coords.Y = snake_c.S_coordinates[snake_length].Y; kill = true;
            draw(appear_coords); Sleep(200); system("cls"); draw(appear_coords); Sleep(200); system("cls"); draw(appear_coords); Sleep(200); system("cls");
            game_over();
        }if (snake_c.S_coordinates[snake_length].X == appear_coords.X && snake_c.S_coordinates[snake_length].Y == appear_coords.Y)
        {
            snake_length_max++; appear_coords = update_coordinates();
            while (snake[appear_coords.X][appear_coords.Y] == true)
            {
                appear_coords = update_coordinates();
            }
        }
        snake_move();
        draw(appear_coords);
        
        //if (GetAsyncKeyState('W') & 0x8000) { // ���'W'���Ƿ񱻰���
        //    if (direction != 1) { direction = 0; }
        //}
        //if (GetAsyncKeyState('S') & 0x8000) { // ���'S'���Ƿ񱻰���
        //    if (direction != 0) { direction = 1; }
        //}if (GetAsyncKeyState('A') & 0x8000) { // ���'A'���Ƿ񱻰���
        //    if (direction != 3) { direction = 2; }
        //}if (GetAsyncKeyState('D') & 0x8000) { // ���'D'���Ƿ񱻰���
        //    if (direction != 2) { direction = 3; }
        //}

        if(GetAsyncKeyState('W') & 0x8000&& direction != 1) { direction = 0; }// ���'W'���Ƿ񱻰���
        else {
            if (GetAsyncKeyState('S') & 0x8000 && direction != 0) { direction = 1; }// ���'W'���Ƿ񱻰���
            else {
                if (GetAsyncKeyState('A') & 0x8000 && direction != 3) { direction = 2; }// ���'W'���Ƿ񱻰���
                else {
                    if (GetAsyncKeyState('D') & 0x8000 && direction != 2) { direction = 3; }// ���'W'���Ƿ񱻰���
                }
            }
        }
        if (GetAsyncKeyState('K') & 0x8000) { // ���'K'���Ƿ񱻰���
            now += 8;
        }
       
    }
    

    return 0;
}